#pragma once

namespace gk
{
	struct GpuProgramConstant
	{
		cr::HashedString				m_hsName;
		cr::HashedString				m_hsType;
		cr::uint32_t					m_offset;
		cr::uint32_t					m_size;
	};

	typedef cr::Handle<GpuProgramConstant> GpuProgramConstantHandle;

	struct GpuProgramConstantTable
	{
		cr::HashedString				m_hsName;
		GpuProgramConstant*				m_pConstants;
		cr::size_t						m_numConstants;

		inline GpuProgramConstantHandle	GetConstantByName(cr::HashedString hsName)
		{
			GpuProgramConstantHandle hConstant;
			for (cr::size_t i = 0; i < m_numConstants; ++i)
			{
				if (m_pConstants[i].m_hsName == hsName)
				{
					hConstant = m_pConstants[i];
					break;
				}
			}
			return hConstant;
		}
	};

	typedef cr::Handle<GpuProgramConstantTable> GpuProgramConstantTableHandle;

	struct GpuProgram
	{
		void*							m_pInitData;
		cr::size_t						m_initDataSize;

		GpuProgramConstantTable			m_constantTables[Constants::MaxConstantTablesPerGpuProgram];
		GpuProgramConstant*				m_pConstants;
		cr::size_t						m_numConstantTables;

		inline GpuProgramConstantTableHandle GetConstantTableByName(cr::HashedString hsName)
		{
			GpuProgramConstantTableHandle hConstantTable;
			for (cr::size_t i = 0; i < m_numConstantTables; ++i)
			{
				if (m_constantTables[i].m_hsName == hsName)
				{
					hConstantTable = m_constantTables[i];
					break;
				}
			}
			return hConstantTable;
		}

		inline GpuProgramConstantHandle GetConstantByName(cr::HashedString hsName)
		{
			for (cr::size_t i = 0; i < m_numConstantTables; ++i)
			{
				for (cr::size_t j = 0; j < m_constantTables[i].m_numConstants; ++j)
				{
					if (m_constantTables[i].m_pConstants[j].m_hsName == hsName)
					{
						return m_constantTables[i].m_pConstants[j];
					}
				}
			}

			return GpuProgramConstantHandle();
		}

		GpuProgramInternal				m_internal;
	};

	typedef cr::Handle<GpuProgram> GpuProgramHandle;
}